tree grammar Evaluador;

options {
  language = Java;
  tokenVocab = ExpresionesParser;
  ASTLabelType = CommonTree;
}

@header {
  package practica12;
  import java.util.Hashtable;
  import java.util.ArrayList;
}

@members {

  //Tabla para guardar variables y valores del arbol general
  Hashtable<String, ArrayList<Float>> variables = new Hashtable<String, ArrayList<Float>> ();
  
  //Lista de funciones
  private ArrayList<MyTree> funciones;
  
//  //Valores de variables propias del subarbol
//  private final Map<String, Float> memoriaLocal = new HashMap<String, Float>();
//  
//  //Indice para acceder al pasado
//  private int index = 0;
//  
//  //Control de error de indices
//  private int indexError = -1;
//  
//  //Constructor publico para el arbol global
//  public ArithmAnasem(CommonTreeNodeStream nodes, LinkedList<MyTree> funciones) {
//      this(nodes);
//      this.funciones = funciones;
//  }
//  
//  //Constructor privado para los subarboles
//  private ArithmAnasem(MyTree funcion, LinkedList<MyTree> funciones, Hashtable<String, LinkedList<Float>> variables, Float parametro) {
//    this(new CommonTreeNodeStream(funcion.getChild(2)), funciones);
//    this.variables = variables;
//    memoriaLocal.put(funcion.getChild(1).getText(), parametro);
//  }
//  
//  //Funcion para buscar por nombre una funcion en la lista de funciones
//  private MyTree buscarFuncion(String name, Float parametro) {
//    for (MyTree f : this.funciones) {
//      if (f.getChild(0).getText().equals(name)) {
//        MyTree id = (MyTree) f.getChild(1);
//        if ((id.getToken().getType() != NUMERIC) || (new Float(id.getToken().getText()).equals(parametro))) 
//          return f;
//      }
//    }
//    return null;
//  }
//  
//  //Funcion para obtener el valor de una variable
//  public Float getValor(String name) {
//    Float valor = memoriaLocal.get(name);
//    if (valor != null)
//      return valor;
//    else {
//      valor = variables.get(name).get(index);
//      if (valor != null)
//        return valor;
//    }
//    return new Float(0);
//  }
  
}




//instrucciones: ^(INSTRS (result = expr {System.out.println("Resultado Expresion: " + $result.result);})*);
//
//expr returns [float result=0] : n=NUMERO {$expr.result = $n.value;}
//                              | ^(oper=MAS izq=expr der=expr) {$expr.result = $izq.result + $der.result; $oper.setResult($result);}
//                              | ^(oper=MENOS izq=expr der=expr) {$expr.result = $izq.result - $der.result; $oper.setResult($result);}
//                              | ^(oper=MULT izq=expr der=expr) {$expr.result = $izq.result * $der.result; $oper.setResult($result);}
//                              | ^(oper=DIV izq=expr der=expr) {$expr.result = $izq.result / $der.result; $oper.setResult($result);};                    
//catch [ArithmeticException ae] {
//}


instrucciones
  : ^(LISTA_INST (a = expr {System.out.println("Resultado Expresion: " + $a.a);})*)
  ;

expr returns [float value = 0] : ^(MAS a=expr b=expr) {$value = a + b; $MAS.setValue(a + b);}
                               | ^(MENOS a = expr b = expr) { $value = a - b; $MENOS.setValue(a - b); }
                               | ^(MULT a = expr b = expr) { $value = a * b; $MULT.setValue(a * b); }
                               | ^(DIV a = expr b = expr) { $value = a / b; $DIV.setValue(a / b); }
                               | IDENT { if (variables.get($ID.text).size() > index) {
                                            Float v = getValor($ID.text);
                                            $value = v; 
                                            $ID.setValue(v);
                                         }
                                         else { //Hemos intentado acceder a un valor inexistente
                                            System.out.println("Error de acceso a una valor inexistente");
                                            Tree childNode = $ID.getParent();
							  								            for (int aux = index - 1; aux > 1; aux--)
								  							               childNode = childNode.getParent();
									  						            Tree parent = childNode.getParent();
										  					            parent.deleteChild(childNode.getChildIndex());
                                         }
                                       }
                               | NUMERO { $value = Float.parseFloat($NUMERIC.text); $NUMERIC.setValue($value); };

  catch [ArithmeticException ae] {
    $value = 0;
  }